#include <dspSimulator/instruction/rint.h>


bool RINT::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return true;
}

void RINT::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                             std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> RINT::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<RINT> rint;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<30>(data, 2, 0b000100000000000001100000000000)) {
            rint = std::make_shared<RINT>(dspInstInfo->getAddress(), baseCycle);
            rint->s = data[1];
            rint->p = data[0];
        }
    }
    return rint;
}

void RINT::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {
//    SGIE bit in TSR → GIE bit in TSR
//    SGIE bit in TSR → GIE bit in CSR
    auto dspMachine = std::dynamic_pointer_cast<DspMachine>(targetMachine);
    auto TSR = dspMachine->getRegisters()->getReg32ByName("TSR")->getDataPtr();
    auto CSR = dspMachine->getRegisters()->getReg32ByName("CSR")->getDataPtr();
    auto SGIE = *TSR & 0x10;
    SGIE >>= 1;
    if (SGIE == 0) {
        *TSR = *TSR & 0xfffffffe;
        *CSR = *CSR & 0xfffffffe;
    } else {
        *TSR = *TSR | 0x1;
        *CSR = *CSR | 0x1;
    }

//    0 → SGIE bit in TSR
    *TSR &= 0xfffffffd;
}

std::string RINT::toString() const {
    return {"RINT"};
}

std::shared_ptr<DspInstruction> RINT::clone() {
    return std::make_shared<RINT>(*this);
}
